
package org.example.javax.security;

import javax.security.auth.callback.*;
import javax.security.sasl.*;
import java.io.IOException;
import java.util.Map;
import java.util.TreeMap;

/**
 * TODO 需要了解
 * SASL（Simple Authentication and Security Layer，简单验证和安全层）是一个安全框架。
 * SASL（发音为 "sassel"）为基于连接的协议提供验证服务以及完整性和保密性服务（可选）。
 * 本章包含以下主题：
 * 简单验证安全层 (Simple Authentication Security Layer, SASL) 介绍
 * SASL 示例
 * 服务提供者的 SASL
 * <p/>
 * http://docs.oracle.com/cd/E19253-01/819-7056/sasl.intro/index.html
 */
public class SASLAuthMain {
  /**
   * @throws javax.security.sasl.SaslException
   */

  public static void main(String[] args) throws SaslException {
    Map<String, String> props = new TreeMap<String, String>();
    props.put(Sasl.QOP, "auth");
    SaslServer saslServer = Sasl.createSaslServer("DIGEST-MD5", "xmpp", "java.com", props, new ServerCallbackHandler());
    byte[] token = new byte[0];
    byte[] challenge = saslServer.evaluateResponse(token);
    SaslClient saslClient = Sasl.createSaslClient(new String[]{"DIGEST-MD5"}, "hans", "xmpp", "java.com", null, new ClientCallbackHandler());
    byte response[];
    if (challenge != null) {
      response = saslClient.evaluateChallenge(challenge);
    } else {
      response = saslClient.evaluateChallenge(null);
    }
    saslServer.evaluateResponse(response);
    if (saslServer.isComplete()) {
      System.out.println("auth success");
    }
  }

  static class ClientCallbackHandler implements CallbackHandler {
    public void handle(Callback[] callbacks) throws IOException,
        UnsupportedCallbackException {
      for (int i = 0; i < callbacks.length; i++) {
        if (callbacks[i] instanceof NameCallback) {
          NameCallback ncb = (NameCallback) callbacks[i];
          ncb.setName("hans");
        } else if (callbacks[i] instanceof PasswordCallback) {
          PasswordCallback pcb = (PasswordCallback) callbacks[i];
          pcb.setPassword("111111".toCharArray());
        } else if (callbacks[i] instanceof RealmCallback) {
          RealmCallback rcb = (RealmCallback) callbacks[i];
          rcb.setText("java.com");
        } else {
          throw new UnsupportedCallbackException(callbacks[i]);
        }
      }
    }
  }

  static class ServerCallbackHandler implements CallbackHandler {
    public ServerCallbackHandler() {
    }

    public void handle(final Callback[] callbacks) throws IOException,
        UnsupportedCallbackException {
      for (Callback callback : callbacks) {
        if (callback instanceof RealmCallback) {
          //do your business
        } else if (callback instanceof NameCallback) {
          //do your business
        } else if (callback instanceof PasswordCallback) {
          ((PasswordCallback) callback).setPassword("111111".toCharArray());
        } else if (callback instanceof AuthorizeCallback) {
          AuthorizeCallback authCallback = ((AuthorizeCallback) callback);
          authCallback.setAuthorized(true);
        } else {
          System.out.println(callback.getClass().getName());
          throw new UnsupportedCallbackException(callback, "Unrecognized Callback");
        }
      }
    }
  }

}



